package com.scalar.chiptrack.adaptor.aati;

import com.scalar.chiptrack.jobs.JobHandler;
import com.scalar.chiptrack.adaptor.AdaptorConstants;
import com.scalar.chiptrack.adaptor.FabSortLot;
import com.scalar.chiptrack.adaptor.AdaptorUtils;
import com.scalar.chiptrack.adaptor.TestLotBinReport;
import com.scalar.chiptrack.adaptor.SortLotBinData;
import com.scalar.chiptrack.adaptor.utils.ParserResult;
import com.scalar.chiptrack.adaptor.utils.Parser;
import com.scalar.chiptrack.adaptor.utils.ParserFactory;
import com.scalar.chiptrack.adaptor.utils.XLSParserImpl;
import com.scalar.chiptrack.adaptor.utils.CSVParserImpl;
import com.scalar.chiptrack.adaptor.dao.TestAdaptorDAO;
import com.scalar.chiptrack.adaptor.dao.AdaptorDAO;
import com.scalar.chiptrack.adaptor.dao.AdaptorRunInfo;
import com.scalar.chiptrack.utils.Logger;
import com.scalar.chiptrack.utils.StringUtils;
import com.scalar.ScalarException;

import java.util.HashMap;
import java.util.ArrayList;
import java.io.File;

/**
 * Created by IntelliJ IDEA.
 * User: munugoti
 * Date: 18 Apr, 2011
 * Time: 4:21:12 PM
 * To change this template use File | Settings | File Templates.
 */
public class UNISEMIPOHYieldDataParser extends JobHandler implements AdaptorConstants
{
    private HashMap<String, FabSortLot> m_sortBinDataMap        = new HashMap<String, FabSortLot>();
    private HashMap<String, FabSortLot> m_sortTotalMap          = new HashMap<String, FabSortLot>();

    private Logger m_parserLogger   = null;
    private String m_dataOutputDir  = null;


    public UNISEMIPOHYieldDataParser() throws ScalarException
    {
        try
        {
            m_dataOutputDir = AdaptorUtils.getDataOutputDir( VENDOR_NAME_UNISEMIPOH, LOCATION_TYPE_TEST);
            AdaptorUtils.makeAllAdaptorDirs( m_dataOutputDir );
            m_parserLogger = AdaptorUtils.getDataParserLogger( m_dataOutputDir,VENDOR_NAME_UNISEMIPOH );
            TestAdaptorDAO.setLogger( m_parserLogger );
            AdaptorUtils.setLogger( m_parserLogger );
        }
        catch (ScalarException se)
        {
            log("ERROR!! ERROR!! ERROR!! Exception while loading UNISEM IPOH WIP output directory details from database, Exception: " + se);
            throw se;
        }
    }
    /**
     *
     * @param args
     * @throws Exception
     */
    public static void main( String args[] ) throws Exception
    {
        try
        {
            new UNISEMIPOHYieldDataParser().execute();
        }
        catch (Exception e)
        {
            throw e;
        }
    }
    /**
     *
     * @throws Exception
     */
    public void execute() throws Exception
    {
        AdaptorUtils.printHeader(VENDOR_NAME_UNISEMIPOH, CONSTANT_PARSER);

        File doneDestDir = new File(  m_dataOutputDir + "/done" );

        File sourceDataoutDir = new File( m_dataOutputDir );

        File[] fileList = sourceDataoutDir.listFiles();
        if ( ( fileList == null ) || ( fileList.length <= 3 ) )
        {
            log( "No file found in directory: " + sourceDataoutDir );
            throw new ScalarException( "\n+-----------No file found in directory " + sourceDataoutDir );
        }

        ArrayList<File> successFileList = new ArrayList<File>();

        boolean success = false;

        for ( int i = 0; i < fileList.length; i++ )
        {
            if ( fileList[i].isDirectory() == true )
            {
                continue;
            }
            try
            {
                //System.out.println("fileList[i].getName() = " + fileList[i].getName());
                if ( fileList[i].getName().startsWith( UNISEMIPOHYieldFTPAdaptor.FILE_NAME_YIELD )  || fileList[i].getName().indexOf( UNISEMIPOHYieldFTPAdaptor.FILE_NAME_YIELD )  != -1)
                {
                    ArrayList<TestLotBinReport> testBinList = parseFTBinReport( fileList[i].getAbsolutePath() );
                    if ( testBinList != null && testBinList.size() > 0 )
                    {
                        //to get the UNISEM Test Bin Details
                        if ( testBinList.isEmpty() == false )
                        {
                            log( "Updating UNISEM IPOH Binning Information" );
                            TestAdaptorDAO.saveTestHardSoftBinInfo ( null, testBinList , VENDOR_NAME_UNISEMIPOH);
                            success = true;
                        }
                        else
                        {
                            log( "UNISEM Binning Information List is Empty" );
                        }
                    }
                    //For Saving the Sort Binning
                    /*ArrayList<SortLotBinData> sortBinList = parseCPBinReport( fileList[i].getAbsolutePath() );

                    if ( sortBinList != null && sortBinList.size() > 0 )
                    {
                        log("updateing the ASET Cp Binning Info....");
                        FabSortAdaptorDAO.saveSortBinInfo( null, sortBinList, VENDOR_NAME_ASET );
                        success = true;
                    }*/

                    successFileList.add(fileList[i]);
                }
                success = true;
            }
            catch ( Exception e )
            {
                success = false;
                log( "Exception while parsing and storing file: " + fileList[i].getAbsolutePath() + "\nException: " + e );
                e.printStackTrace();
                throw e;
            }
        }//end of FOR loop

        // To Close the Drop Out Lots
        AdaptorDAO.closeDropOutLots(VENDOR_NAME_UNISEMIPOH);
        // TO SEND THE NEW LOTS, NEW TRANSIT LOTS, NO PO LOTS, DISCREPANCY LOTS NOTIFICATIONS TO THE USER
        AdaptorDAO.sendAllNotifications(VENDOR_NAME_UNISEMIPOH, true, true, true);

        int adaptor_id = AdaptorRunInfo.getLastRunAdaptorId( UNISEMIPOHYieldFTPAdaptor.ADAPTOR_NAME, CONSTANT_ADAPTOR);
        // Update Adaptor_Run_Info table
        try
        {
            if ( success == true )
            {
                AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, UNISEMIPOHYieldFTPAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
                System.out.println( "SUCCESSFULLY UPDATED IN THE DATABASE" );
            }
        }
        catch ( ScalarException se )
        {
            success = false; //As filES DATA SAVED , UPDATEING AS SUCCESS
            AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, UNISEMIPOHYieldFTPAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
            log( "WARNING!! WARNING!! WARNING!! Could not update Adaptor run information, Exception: " + se );
            throw se;
        }
        // Move the successful files to 'done' directory
       if ( success )
       {
           AdaptorUtils.moveFilesToDone( successFileList, doneDestDir );
       }
    }

    private ArrayList<TestLotBinReport> parseFTBinReport( String fileName ) throws Exception
    {
        if ( fileName == null ) throw new ScalarException( "Filename argument is null" );
        ParserResult result     = null;

        String lotNumber        = null;
        String partNumber       = null;
        String fablotNumber     = null;
        ArrayList<TestLotBinReport> ftYieldList  = new ArrayList<TestLotBinReport>();

        try
        {
            File detailWipFile = new File( fileName );
            if ( detailWipFile.exists() == false )
            {
                throw new ScalarException( fileName + " doesnt exist" );
            }

            log( "\nFound " + fileName );
            log( "\nParsing the file for Ft Yield Report..." );
            System.out.println( "\nFound " + fileName );
            System.out.println( "\nParsing the file for FT Yield Report..." );

            Parser parser = ParserFactory.getCSVParser( detailWipFile, ',' );

            ((CSVParserImpl)parser).setHeaderRowIdx(1);
            ((CSVParserImpl)parser).setDataStartRowIdx(2);

            result = parser.parse();
            //System.out.println("result.getString() = " + result.getHeadings() );
            while ( result.next() )
            {
                partNumber   = result.getString("Device");
                fablotNumber = result.getString("Wafer Lot No");
                lotNumber    = result.getString("Subcon Lot No");
                if ( lotNumber == null)
                {
                    lotNumber = fablotNumber;
                }
                if ( partNumber != null && partNumber.length() > 0 && lotNumber != null && lotNumber.length() > 0 )
                {
                    TestLotBinReport ftYieldStatus = new TestLotBinReport();

                    partNumber = partNumber.split("\\(")[0];
                    
                    ftYieldStatus.setDeviceName( partNumber );
                    ftYieldStatus.setLotNumber( lotNumber );
                    ftYieldStatus.setCustLotNo( fablotNumber );
                    //ftYieldStatus.setPoNumber( result.getString("Release No"));
                    ftYieldStatus.setPkgType( result.getString("Package") );
                    ftYieldStatus.setLeadCount( result.getString("L/C") );
                    ftYieldStatus.setStage( result.getString("Insertion") ); // Insertion
                    ftYieldStatus.setTestProg(result.getString("Program No"));
                    ftYieldStatus.setTesterId( result.getString("Tester ID") );
                    ftYieldStatus.setDateCode( result.getString("Date Code") );
                    ftYieldStatus.setHandler( result.getString("Handler ID") );
                    ftYieldStatus.setLb(result.getString("L/B ID"));
                    ftYieldStatus.setTemp( result.getString("Temp"));
                    ftYieldStatus.setDutBoardNo( result.getString("DUT Board No"));
                    ftYieldStatus.setDutCableNo( result.getString("DUT Cable No"));
                    ftYieldStatus.setDateIn( StringUtils.formatDate( result.getString("Test In Date"),"yyyy-MM-dd HH:mm:ss","MM/dd/yyyy HH:mm:ss" ) );
                    ftYieldStatus.setDateOut(StringUtils.formatDate( result.getString("Test Out Date"),"yyyy-MM-dd HH:mm:ss", "MM/dd/yyyy HH:mm:ss" ) );
                    ftYieldStatus.setInQty( result.getInt("In Qty") +"");
                    ftYieldStatus.setPassQty( result.getInt("Out Qty")+"" );
                    //ftYieldStatus.setDamageQty( result.getString("Defect Qty") );
                    ftYieldStatus.setYield( result.getString("Yield").replaceAll("%","") );
                    ftYieldStatus.setBin1( result.getString("Hard Bin 1") );
                    ftYieldStatus.setBin2(result.getString("Hard Bin 2"));
                    ftYieldStatus.setBin3(result.getString("Hard Bin 3"));
                    ftYieldStatus.setBin4(result.getString("Hard Bin 4"));
                    ftYieldStatus.setBin5(result.getString("Hard Bin 5"));
                    ftYieldStatus.setBin6(result.getString("Hard Bin 6"));
                    ftYieldStatus.setBin7(result.getString("Hard Bin 7"));
                    ftYieldStatus.setBin8(result.getString("Hard Bin 8"));

                    ftYieldStatus.setLossQty( result.getString("Loss QTY") );
                    ftYieldStatus.setVmQty( result.getString("VM QTY") );
                    ftYieldStatus.setOsQty( result.getString("OS QTY") );
                    ftYieldStatus.setOSRate( result.getString("OS Yield") );

                    int[] binQty = new int[100];
                    int binNo = 0;
                    for(int i=1; i<=40; i++ )
                    {
                        binQty[binNo++] = result.getInt("Soft Bin "+i);
                    }

                    ftYieldStatus.setSoftbinQty( binQty );
                    ftYieldList.add( ftYieldStatus );

                }
            }
        }
        catch ( Exception ex )
        {
            System.out.println("ERROR!!!ERROR!!! While Parsing the UNISEM Ipoh FT Yield Report");
            ex.printStackTrace();
            throw ex;
        }

        return ftYieldList;
    }

    private ArrayList<SortLotBinData> parseCPBinReport( String fileName ) throws Exception
    {
        if ( fileName == null ) throw new ScalarException( "Filename argument is null" );
        ParserResult result     = null;

        String lotNumber        = null;
        String partNumber       = null;
        String fablotNumber     = null;
        FabSortLot sortBinTotalLot = null;
        FabSortLot sortBinLot   = null;
        ArrayList<SortLotBinData> cpYieldList  = new ArrayList<SortLotBinData>();
        int waferId             = 0;
        HashMap waferIdMap = new HashMap();
        try
        {
            File detailWipFile = new File( fileName );
            if ( detailWipFile.exists() == false )
            {
                throw new ScalarException( fileName + " doesnt exist" );
            }

            log( "\nFound " + fileName );
            log( "\nParsing the file for CP Yield Report..." );
            System.out.println( "\nFound " + fileName );
            System.out.println( "\nParsing the file for CP Yield Report..." );

            Parser parser = ParserFactory.getXLSParser( detailWipFile, "WS" );

            ((XLSParserImpl)parser).setHeaderRowIdx(2);
            ((XLSParserImpl)parser).setDataStartRowIdx(3);

            result = parser.parse();

            //System.out.println("result.getString() = " + result.getHeadings() );
             while ( result.next() )
            {
                partNumber = result.getString("Device");
                lotNumber = result.getString("Wafer Lot No");
                waferId   = result.getInt("Wafer #");

                if (partNumber!= null && partNumber.trim().length()>0 && lotNumber != null && lotNumber.trim().length() > 0 && waferId > 0 && waferId < 26 )
                {
                    sortBinTotalLot = (FabSortLot) m_sortTotalMap.get( partNumber + lotNumber);

                    if ( sortBinTotalLot == null )
                    {
                        sortBinTotalLot = new FabSortLot( VENDOR_NAME_UNISEMIPOH, LOCATION_TYPE_SORT );
                        m_sortTotalMap.put( partNumber + lotNumber  , sortBinTotalLot );
                    }
                    int m_totalProbeQty         = 0;
                    int m_totalPassQty          = 0;
                    int m_waferQtyIn            = 0;
                    if ( sortBinTotalLot.getQtyIn() != null )
                    {

                        try
                       {
                           m_waferQtyIn = Integer.parseInt( sortBinTotalLot.getQtyIn() );
                       }
                       catch ( NumberFormatException ignore )
                       {
                       }

                       m_totalPassQty = sortBinTotalLot.getTotalgoodDieQtyIn();
                       m_totalProbeQty = sortBinTotalLot.getTotalprobeQtyIn();

                       if ( !waferIdMap.containsKey( partNumber + lotNumber + waferId ) )
                       {
                           waferIdMap.put( partNumber + lotNumber+waferId, waferId );

                           m_waferQtyIn += 1;
                           m_totalPassQty += result.getInt("Good Dies");
                           m_totalProbeQty += result.getInt("GDPW");
                       }
                    }
                    else
                    {
                        if ( !waferIdMap.containsKey( partNumber + lotNumber+waferId ) )
                        {
                            waferIdMap.put( partNumber + lotNumber+waferId, waferId );
                            m_waferQtyIn = 1;
                            m_totalPassQty = result.getInt("Good Dies");
                            m_totalProbeQty = result.getInt("GDPW");
                        }
                     }
                     sortBinTotalLot.setQtyIn( m_waferQtyIn+"");
                     sortBinTotalLot.setTotalgoodDieQtyIn( m_totalPassQty);
                     sortBinTotalLot.setTotalprobeQtyIn( m_totalProbeQty );
                }
            }
            //FOR Restting the Row Index
            result.reset();

            while ( result.next() )
            {
                partNumber   = result.getString("Device");
                fablotNumber = result.getString("Wafer Lot No");
                /*lotNumber    = result.getString("Subcon Lot No");*/
                if ( lotNumber == null)
                {
                    lotNumber = fablotNumber;
                }
                waferId   = result.getInt("Wafer #");
                if ( partNumber != null && partNumber.length() > 0 && lotNumber != null && lotNumber.length() > 0 && waferId > 0 && waferId < 26 )
                {
                    SortLotBinData cpYieldStatus = new SortLotBinData();

                    sortBinLot = ( FabSortLot ) m_sortBinDataMap.get( partNumber + fablotNumber + waferId);

                    if ( sortBinLot == null )
                    {
                        sortBinLot = new FabSortLot( VENDOR_NAME_ASET, LOCATION_TYPE_SORT );
                        m_sortBinDataMap.put( partNumber + fablotNumber + waferId  , sortBinLot );
                    }
                    sortBinLot.setCustProduct( partNumber );
                    sortBinLot.setLotId( fablotNumber );
                    sortBinLot.setFabLotNumber( fablotNumber );
                    sortBinLot.setWaferID( waferId+"" );
                     // WAFER QTY IN Always Same(total wafers) ,But For Each every Wafer update the Wafer Qty, the the WaferQty
                    sortBinLot.setQtyIn( m_sortTotalMap.get(partNumber + fablotNumber).getQtyIn() +"");
                    sortBinLot.setTotalgoodDieQtyIn( m_sortTotalMap.get(partNumber + fablotNumber).getTotalgoodDieQtyIn() );
                    sortBinLot.setTotalprobeQtyIn( m_sortTotalMap.get(partNumber + fablotNumber).getTotalprobeQtyIn() );
                    sortBinLot.setDateOut( StringUtils.formatDate(result.getString("Test Out Date"), "yyyy/MM/dd HH:mm:ss", "MM/dd/yyyy HH:mm:ss" ) );
                    sortBinLot.setDateIn( StringUtils.formatDate(result.getString("Test In Date"),"yyyy/MM/dd HH:mm:ss", "MM/dd/yyyy HH:mm:ss" ) );
                    sortBinLot.setTesterNo( result.getString("Tester ID") );
                    sortBinLot.setTestProgram( result.getString("Program No") );
                    sortBinLot.setGoodDieQtyIn(result.getInt("Good Dies"));
                    sortBinLot.setRejectedQtyIn(result.getInt("GDPW")-result.getInt("Good Dies"));
                    System.out.println("result.getString(\"Yield\") = " + result.getString("Yield"));
                    System.out.println("result.getDouble(\"Yield\") = " + result.getDouble("Yield"));
                    sortBinLot.setShipYield(result.getString("Yield").replaceAll("%","") );
                    sortBinLot.setTotalYield( 0 ); // if sets as 0, in the PROC Yield Calculating (INQTY *100.00/OUTQTY)
                    sortBinLot.setBinNumber( "Bin1" );

                    cpYieldStatus.setProduct( partNumber );
                    cpYieldStatus.setLotNumber(fablotNumber );
                    cpYieldStatus.setFablotNumber( fablotNumber );
                    cpYieldStatus.setTemp(result.getString("Temperature"));
                    cpYieldStatus.setProbeId(result.getString("Prober ID"));
                    cpYieldStatus.setProbeCard(result.getString("Probe Card"));
                    cpYieldStatus.setInsertion(result.getString("Insertion"));
                    cpYieldStatus.setLB(result.getString("Load Board"));
                    cpYieldStatus.setGrossDice( result.getInt("GDPW")+"");
                    cpYieldStatus.setGoodDice( result.getInt("Good Dies")+"");
                    cpYieldStatus.setShipYield( result.getString("Yield").replaceAll("%","") );
                    cpYieldStatus.setWaferId( waferId+"");
                    cpYieldStatus.setDateIn( StringUtils.formatDate(result.getString("Test In Date"), "yyyy/MM/dd HH:mm:ss", "MM/dd/yyyy HH:mm:ss" ) );
                    int[] binQty = new int[100];
                    int binNo = 0;
                    for(int i=1; i<=100; i++ )
                    {
                        binQty[binNo++] = result.getInt("Bin "+i);
                    }

                    cpYieldStatus.setBinQty( binQty );
                    cpYieldList.add( cpYieldStatus );

                }
            }
        }
        catch ( Exception ex )
        {
            System.out.println("ERROR!!!ERROR!!! While Parsing the ASET CP Yield Report");
            ex.printStackTrace();
            throw ex;
        }

        return cpYieldList;
    }
    private void log( String message )
    {
        if ( message == null ) return;

        if ( m_parserLogger != null )
        {
            m_parserLogger.logDebug( message + LINE_SEPARATOR );
        }
        else
        {
            System.out.println( message );
        }
    } // end of log method
}

